package authValid

import (
	"appService/src/application/admin/admin/adminModels"
	"appService/src/application/app/appModels"
	"appService/src/application/app/authGroup"
	"appService/src/authValid/dataAuth"
	"appService/src/authValid/userAuthType"
	"appService/src/config"
	"appService/src/orm"
	"errors"
	"github.com/gogf/gf/container/gmap"
	"github.com/gogf/gf/frame/g"
	"os"
)

/*
➤
✿
┏━
┣━
┗━
*/
var (
	//路由信息缓存到内存中,并且启用线程安全，开启读写锁(默认线程不安全)
	apiMap *gmap.StrAnyMap = gmap.NewStrAnyMap(true)
	//部门机构信息缓存到内存中,并且启用线程安全，开启读写锁(默认线程不安全)
	branchMap *gmap.StrAnyMap = gmap.NewStrAnyMap(true)
	//权限角色信息缓存到内存中,并且启用线程安全，开启读写锁(默认线程不安全)
	rolesMap *gmap.StrAnyMap = gmap.NewStrAnyMap(true)
	//菜单权限信息缓存到内存中,并且启用线程安全，开启读写锁(默认线程不安全)
	authMap *gmap.StrAnyMap = gmap.NewStrAnyMap(true)
	//文件夹权限信息缓存到内存中,并且启用线程安全，开启读写锁(默认线程不安全)
	folderMap *gmap.StrAnyMap = gmap.NewStrAnyMap(true)
)

// 初始化数据接口验证
func Init() {
	g.Log().Info("┏━➤ 初始化数据接口验证")
	apiList := make([]adminModels.Api, 0)
	err := orm.Db.Find(&apiList)
	if err != nil {
		g.Log().Errorf("┗━❌ 查询接口，错误：%v", err)
		os.Exit(2)
	}
	for _, v := range apiList {
		apiMap.Set(v.AuthCode, v)
	}
	rolesList := make([]adminModels.Roles, 0)
	err = orm.Db.Find(&rolesList)
	if err != nil {
		g.Log().Errorf("┗━❌ 查询角色，错误：%v", err)
		os.Exit(2)
	}
	for _, v := range rolesList {
		rolesMap.Set(v.Id, v)
	}
	authList := make([]adminModels.Auth, 0)
	err = orm.Db.Find(&authList)
	if err != nil {
		g.Log().Errorf("┗━❌ 查询菜单权限，错误：%v", err)
		os.Exit(2)
	}
	for _, v := range authList {
		authMap.Set(v.Id, v)
	}
	branchList := make([]adminModels.Branch, 0)
	err = orm.Db.Find(&branchList)
	if err != nil {
		g.Log().Errorf("┗━❌ 查询部门机构，错误：%v", err)
		os.Exit(2)
	}
	for _, v := range branchList {
		branchMap.Set(v.Id, v)
	}
	folderList := make([]appModels.Folder, 0)
	err = orm.Db.Asc("sort").Find(&folderList)
	if err != nil {
		g.Log().Errorf("┗━❌ 查询文件夹，错误：%v", err)
		os.Exit(2)
	}
	for _, v := range folderList {
		folderMap.Set(v.Id, v)
	}
	g.Log().Info("┗━✿ 数据接口初始化完成")
}

// 路由标识获取路由信息
func AuthCodeGetRoute(code string) *adminModels.Api {
	val := apiMap.Get(code)
	if val != nil {
		api := val.(adminModels.Api)
		return &api
	} else {
		return nil
	}
}

// 角色ID获取角色信息
func GetRole(id string) *adminModels.Roles {
	val := rolesMap.Get(id)
	if val != nil {
		role := val.(adminModels.Roles)
		return &role
	} else {
		return nil
	}
}

// 菜单ID获取菜单信息
func GetAuth(id string) *adminModels.Auth {
	val := authMap.Get(id)
	if val != nil {
		auth := val.(adminModels.Auth)
		return &auth
	} else {
		return nil
	}
}

//获取指定部门及子部门的所有角色ID
func GetBranchAllRoles(pid string, authGroupId string) map[string]bool {
	//使用map存放避免重复 key 为角色ID
	temMap := make(map[string]bool)
	if config.BranchAuthOpen {
		list := branchMap.Values()
		for _, val := range list {
			tem := val.(adminModels.Branch)
			if tem.Pid == pid {
				for _, v := range tem.Roles {
					if v.AuthGroupId == authGroupId {
						for _, id := range v.Roles {
							temMap[id] = true
						}
					}
				}
			}
		}
		for id, _ := range temMap {
			tMap := GetBranchAllRoles(id, authGroupId)
			for tid, _ := range tMap {
				temMap[tid] = true
			}
		}
	}
	return temMap
}

// 获取用户拥有的角色ID和所属部门及子部门的角色ID
func GetUserAllRoles(loginUser *appModels.UserInfo) map[string]bool {
	//使用map存放避免重复 key 为角色ID
	temMap := make(map[string]bool)
	// 获取用户本身的权限角色
	for _, id := range loginUser.User.Roles {
		temMap[id] = true
	}
	// 获取用户所属部门机构的权限角色和所有子部门的权限角色ID
	if config.BranchAuthOpen {
		val := branchMap.Get(loginUser.User.Bid)
		if val != nil {
			branch := val.(adminModels.Branch)
			for _, v := range branch.Roles {
				if v.AuthGroupId == loginUser.User.AuthGroupId {
					for _, id := range v.Roles {
						temMap[id] = true
					}
				}
			}
			bMap := GetBranchAllRoles(branch.Id, loginUser.User.AuthGroupId)
			for id, _ := range bMap {
				temMap[id] = true
			}
		}
	}
	return temMap
}

// 判断路由标识用户是否有权限访问
//【api:数据权限 】【code:当前数据权限标识 】【loginUser:当前登录用户】
func UserIsToAuthCode(api *adminModels.Api, code string, loginUser *appModels.UserInfo) bool {
	if loginUser.Account.AccountType == userAuthType.SYSTEM_ADMIN {
		return true
	}
	if api.Visit == dataAuth.SYSTEM {
		return false
	}
	userRoleMap := GetUserAllRoles(loginUser)
	for id, _ := range userRoleMap {
		role := GetRole(id)
		if role != nil {
			for _, apiCode := range role.DefaultApiCode {
				if apiCode == code {
					return true
				}
			}
			for _, apiCode := range role.ApiCode {
				if apiCode == code {
					return true
				}
			}
		}
	}
	return false
}

// 获取用户可以访问的数据（接口）权限标识数组
func GetUserAuthCodeList(loginUser *appModels.UserInfo) *[]string {
	list := make([]string, 0)
	apiList := apiMap.Values()
	aMap := make(map[string]adminModels.Api)
	apiCodeMap := make(map[string]adminModels.Api)
	if loginUser.Account.AccountType == userAuthType.SYSTEM_ADMIN {
		for _, v := range apiList {
			a := v.(adminModels.Api)
			if a.AuthGroupId == authGroup.SHARE_ID || a.AuthGroupId == loginUser.User.AuthGroupId {
				list = append(list, a.AuthCode)
			}
		}
		return &list
	} else {
		for _, vi := range apiList {
			v := vi.(adminModels.Api)
			aMap[v.AuthCode] = v
			if v.Visit < dataAuth.AUTH {
				//添加 公开的和只需登陆的api权限
				if v.AuthGroupId == authGroup.SHARE_ID || v.AuthGroupId == loginUser.User.AuthGroupId {
					apiCodeMap[v.AuthCode] = v
				}
			}
		}
	}
	// 添加指定api权限
	userRoleMap := GetUserAllRoles(loginUser)
	for id, _ := range userRoleMap {
		role := GetRole(id)
		if role != nil {
			for _, apiCode := range role.ApiCode {
				a, ok := aMap[apiCode]
				if ok {
					apiCodeMap[apiCode] = a
				}
			}
			for _, apiCode := range role.DefaultApiCode {
				a, ok := aMap[apiCode]
				if ok {
					apiCodeMap[apiCode] = a
				}
			}
		}
	}
	for _, v := range apiCodeMap {
		list = append(list, v.AuthCode)
	}
	return &list
}

// 获取用户可以访问的数据（接口）权限列表
func GetUserApiList(loginUser *appModels.UserInfo) *[]adminModels.Api {
	list := make([]adminModels.Api, 0)
	apiList := apiMap.Values()
	aMap := make(map[string]adminModels.Api)
	apiCodeMap := make(map[string]adminModels.Api)
	if loginUser.Account.AccountType == userAuthType.SYSTEM_ADMIN {
		for _, v := range apiList {
			a := v.(adminModels.Api)
			if a.AuthGroupId == authGroup.SHARE_ID || a.AuthGroupId == loginUser.User.AuthGroupId {
				list = append(list, a)
			}
		}
		return &list
	} else {
		for _, vi := range apiList {
			v := vi.(adminModels.Api)
			aMap[v.AuthCode] = v
			if v.Visit < dataAuth.AUTH {
				//添加 公开的和只需登陆的api权限
				if v.AuthGroupId == authGroup.SHARE_ID || v.AuthGroupId == loginUser.User.AuthGroupId {
					apiCodeMap[v.AuthCode] = v
				}
			}
		}
	}
	// 添加指定api权限
	userRoleMap := GetUserAllRoles(loginUser)
	for id, _ := range userRoleMap {
		role := GetRole(id)
		if role != nil {
			for _, apiCode := range role.ApiCode {
				a, ok := aMap[apiCode]
				if ok {
					apiCodeMap[apiCode] = a
				}
			}
			for _, apiCode := range role.DefaultApiCode {
				a, ok := aMap[apiCode]
				if ok {
					apiCodeMap[apiCode] = a
				}
			}
		}
	}
	for _, v := range apiCodeMap {
		list = append(list, v)
	}
	return &list
}

// 获取用户可以访问的菜单列表 omitApi:是否排除 页面默认数据接口ID列表 和 页面对应数据接口列表
func GetUserAuthList(loginUser *appModels.UserInfo, omitApi bool) *[]adminModels.Auth {
	list := make([]adminModels.Auth, 0)
	authList := authMap.Values()
	aMap := make(map[string]adminModels.Auth)   // 所有菜单权限
	temMap := make(map[string]adminModels.Auth) // 可访问的菜单权限
	if loginUser.Account.AccountType == userAuthType.SYSTEM_ADMIN {
		for _, vi := range authList {
			v := vi.(adminModels.Auth)
			if v.AuthGroupId == loginUser.User.AuthGroupId {
				if omitApi {
					v.DefaultApiList = nil
					v.ApiList = nil
				}
				list = append(list, v)
			}
		}
	} else {
		for _, vi := range authList {
			v := vi.(adminModels.Auth)
			aMap[v.Id] = v
			//添加 公开的和只需登陆的菜单权限
			if v.AuthGroupId == loginUser.User.AuthGroupId {
				if loginUser.User.AuthGroupId == v.AuthGroupId && v.Visit < dataAuth.AUTH {
					temMap[v.Id] = v
				}
			}
		}
		// 添加指定菜单权限
		userRoleMap := GetUserAllRoles(loginUser)
		for id, _ := range userRoleMap {
			role := GetRole(id)
			if role != nil {
				for _, id := range role.AuthId {
					auth, ok := aMap[id]
					if ok && loginUser.User.AuthGroupId == auth.AuthGroupId && auth.Visit == dataAuth.AUTH {
						temMap[auth.Id] = auth
					}
				}
			}
		}
		for _, v := range temMap {
			if omitApi {
				v.DefaultApiList = nil
				v.ApiList = nil
			}
			list = append(list, v)
		}
	}
	// 排序
	for i := 0; i < len(list); i++ {
		for y := i; y < len(list); y++ {
			if list[i].Sort > list[y].Sort {
				tem := list[i]
				list[i] = list[y]
				list[y] = tem
			}
		}
	}
	return &list
}

// 获取公开的api数据（接口）权限
func GetPublicApiCode(authGroupId string) *[]string {
	list := make([]string, 0)
	apiList := apiMap.Values()
	for _, v := range apiList {
		if v != nil {
			api := v.(adminModels.Api)
			if (api.AuthGroupId == authGroup.SHARE_ID || api.AuthGroupId == authGroupId) && api.Visit == dataAuth.PUBLIC {
				list = append(list, api.AuthCode)
			}
		}
	}
	return &list
}

//获取公开的菜单
func GetPublicAuth(authGroupId string) *[]adminModels.Auth {
	list := make([]adminModels.Auth, 0)
	authList := authMap.Values()
	for _, v := range authList {
		if v != nil {
			auth := v.(adminModels.Auth)
			if auth.AuthGroupId == authGroupId && auth.Visit == dataAuth.PUBLIC {
				list = append(list, auth)
			}
		}
	}
	// 排序
	for i := 0; i < len(list); i++ {
		for y := i; y < len(list); y++ {
			if list[i].Sort > list[y].Sort {
				tem := list[i]
				list[i] = list[y]
				list[y] = tem
			}
		}
	}
	return &list
}

// 获取当前用户可访问的部门机构ID列表 isBid: 是否可以访问账号所属部门机构
func GetBranchIDs(loginUser *appModels.UserInfo,isBid bool) *[]string {
	list := make([]string, 0)
	if config.RolesBranchOpen {
		temMap := make(map[string]string)
		// 是否可以访问账号所属部门机构
		if isBid {
			temMap[ loginUser.Account.Bid] =  loginUser.Account.Bid
		}
		if loginUser.Account.AccountType == dataAuth.SYSTEM{
			for _, branch := range branchMap.Values(){
				bid:=branch.(adminModels.Branch).Id
				temMap[bid] = bid
			}
		}else{
			for _, id := range loginUser.User.Roles {
				role := GetRole(id)
				if role != nil {
					for _, bid := range role.BranchId {
						temMap[bid] = bid
					}
				}
			}
		}
		for _, v := range temMap {
			list = append(list, v)
		}
	}
	return &list
}

// 删除接口
func ApiRemove(code string) {
	apiMap.Remove(code)
}

// 添加修改接口
func ApiSet(route *adminModels.Api) {
	apiMap.Set(route.AuthCode, *route)
}

// 删除角色
func RoleRemove(id string) {
	rolesMap.Remove(id)
}

// 添加修改角色
func RoleSet(role *adminModels.Roles) {
	rolesMap.Set(role.Id, *role)
}

// 删除菜单权限
func AuthRemove(id string) {
	authMap.Remove(id)
}

// 添加修改菜单权限
func AuthSet(auth *adminModels.Auth) {
	authMap.Set(auth.Id, *auth)
}

// 删除部门机构
func BranchRemove(branchId string) {
	branchMap.Remove(branchId)
}

// 添加修改部门机构
func BranchSet(branch *adminModels.Branch) {
	branchMap.Set(branch.Id, *branch)
}

// 删除文件夹
func FolderRemove(folderId string) {
	folderMap.Remove(folderId)
}

// 添加修改文件夹
func FolderSet(folder *appModels.Folder) {
	folderMap.Set(folder.Id, *folder)
}

//获取用户可以访问的文件夹
func GetALLUserFolder(loginUser *appModels.UserInfo) *[]appModels.Folder {
	resList := make([]appModels.Folder, 0)
	ids := GetAllUserFolderIds(loginUser)
	for _, v := range *ids {
		tem := folderMap.Get(v)
		if tem != nil {
			resList = append(resList, tem.(appModels.Folder))
		}
	}
	// 排序
	for i := 0; i < len(resList); i++ {
		for y := i; y < len(resList); y++ {
			if resList[i].Sort > resList[y].Sort {
				tem := resList[i]
				resList[i] = resList[y]
				resList[y] = tem

			} else if resList[i].Sort == resList[y].Sort {
				if resList[i].Created.Unix() > resList[y].Created.Unix() {
					tem := resList[i]
					resList[i] = resList[y]
					resList[y] = tem
				}
			}

		}
	}
	return &resList
}

//获取用户可以访问的文件夹ID数组
func GetAllUserFolderIds(loginUser *appModels.UserInfo) *[]string {
	resList := make([]string, 0)
	folderList := folderMap.Values()
	temRolesMap := GetUserAllRoles(loginUser)
	for _, v := range folderList {
		tem := v.(appModels.Folder)
		if config.FilesAuthOpen {
			if tem.Pid == "" {
				temIds := GetUserFolderAllChildren(tem.Id, loginUser, temRolesMap)
				if len(*temIds) > 0 {
					resList = append(resList, *temIds...)
				}
			}
		} else {
			resList = append(resList, tem.Id)
		}
	}
	return &resList
}

// 递归获取文件夹ID(不验证权限)
func getFolderAndChildrenIds(temRolesMap map[string]bool, pid string) []string {
	folderList := folderMap.Values()
	temMap := make([]string, 0)
	for _, val := range folderList {
		tem := val.(appModels.Folder)
		if tem.Pid == pid {
			temMap = append(temMap, tem.Id)
		}
	}
	for _, id := range temMap {
		tMap := getFolderAndChildrenIds(temRolesMap, id)
		for _, tid := range tMap {
			temMap = append(temMap, tid)
		}
	}
	return temMap
}

//获取指定文件夹(有访问权限)及下面的子文件夹ID userRoles 权限角色map
func GetUserFolderAllChildren(folderId string, loginUser *appModels.UserInfo, userRoles ...map[string]bool) *[]string {
	var temRolesMap map[string]bool
	if len(userRoles) > 0 {
		temRolesMap = userRoles[0]
	} else {
		temRolesMap = GetUserAllRoles(loginUser)
	}
	temFolder := folderMap.Get(folderId)
	if temFolder == nil {
		return &[]string{}
	}
	folder := temFolder.(appModels.Folder)
	if FolderCheckUser(&folder, loginUser, temRolesMap) {
		resList := getFolderAndChildrenIds(temRolesMap, folderId)
		resList = append(resList, folderId)
		return &resList
	}
	return &[]string{}
}

// 获取指定文件夹的根文件夹
func GetFolderRoot(pid string) *appModels.Folder {
	temFolder := folderMap.Get(pid)
	if temFolder == nil {
		return nil
	}
	fo := temFolder.(appModels.Folder)
	if fo.Pid == "" {
		return &fo
	} else {
		return GetFolderRoot(fo.Pid)
	}
}

// 判断指定的文件夹用户是否可以访问 userRoles 权限角色map
func FolderCheckUser(folder *appModels.Folder, loginUser *appModels.UserInfo, userRoles ...map[string]bool) bool {
	if config.FilesAuthOpen {
		if folder.Pid != "" {
			folder = GetFolderRoot(folder.Pid)
		}
		if folder.Visit == dataAuth.PUBLIC {
			return true
		}
		if !loginUser.IsLogin {
			return false
		}
		if folder.Visit == dataAuth.LOGIN {
			return true
		}
		if loginUser.Account.AccountType == userAuthType.SYSTEM_ADMIN {
			return true
		} else {
			var temRolesMap map[string]bool
			if len(userRoles) > 0 {
				temRolesMap = userRoles[0]
			} else {
				temRolesMap = GetUserAllRoles(loginUser)
			}
			for _, r := range folder.Roles {
				if r.AuthGroupId == loginUser.User.AuthGroupId {
					for _, rId := range r.Roles {
						for trId, _ := range temRolesMap {
							if rId == trId {
								return true
							}
						}
					}
				}
			}
		}
		return false
	} else {
		return true
	}
}

// 获取指定的文件夹信息 msgName:第一个为 类型（文件夹、文件、图片 等），第二个为名称
func FolderIdGetFolder(folderId string, loginUser *appModels.UserInfo, msgName ...string) (*appModels.Folder, error) {
	txtName := "文件夹"
	if len(msgName) > 0 {
		txtName = msgName[0]
	}
	temFolder := folderMap.Get(folderId)
	if temFolder == nil {
		return nil, errors.New("文件夹不存在")
	}
	folder := temFolder.(appModels.Folder)
	fileName := folder.FolderName
	if len(msgName) > 1 {
		fileName = msgName[1]
	}
	if FolderCheckUser(&folder, loginUser) {
		return &folder, nil
	} else {
		return nil, errors.New("o(╥﹏╥)o您没有权限操作" + txtName + " " + fileName)
	}
}

// 判断指定的文件夹是否存在
func FolderContains(folderId string) bool {
	return folderMap.Contains(folderId)
}
